import re

from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q
from django.utils import timezone
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.views import APIView
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework_simplejwt.exceptions import TokenError
from rest_framework_simplejwt.tokens import RefreshToken

from .models import User
from .serializers import UserCreateSerializer, UserUpdateSerializer, UserRegistrationSerializer, UserListSerializer, \
    UserSerializer, UserInfoSerializer
from ..utils.pageNumberPagination import CustomPageNumberPagination
from ..utils.response_utils import api_response, ResponseCode


class RegisterView(APIView):
    """
    用户注册接口
    """

    permission_classes = [AllowAny]
    authentication_classes = []

    @swagger_auto_schema(
        operation_description="注册用户",
        request_body=UserRegistrationSerializer,
        responses={
            200: openapi.Response(
                description="注册成功",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'code': openapi.Schema(type=openapi.TYPE_INTEGER, description="响应状态码"),
                        'msg': openapi.Schema(type=openapi.TYPE_STRING, description="响应消息"),
                        'data': openapi.Schema(
                            type=openapi.TYPE_OBJECT,
                            properties={
                                'id': openapi.Schema(type=openapi.TYPE_STRING, description="用户 ID"),
                                'username': openapi.Schema(type=openapi.TYPE_STRING, description="用户名"),
                                'email': openapi.Schema(type=openapi.TYPE_STRING, description="邮箱"),
                                'phone': openapi.Schema(type=openapi.TYPE_STRING, description="用户电话"),
                                'user_type': openapi.Schema(type=openapi.TYPE_INTEGER, description="用户类型"),
                                'status': openapi.Schema(type=openapi.TYPE_STRING,
                                                         description="用户是否激活（启用enable、禁用disabled）"),
                            }
                        )
                    }
                )
            ),
            400: openapi.Response(description="请求数据无效"),
            500: openapi.Response(description="服务器内部错误")
        },
        tags=["登录注册"]
    )
    def post(self, request, *args, **kwargs):
        serializer = UserRegistrationSerializer(data=request.data)
        if serializer.is_valid():
            try:
                user = serializer.save()
                return api_response(ResponseCode.SUCCESS, "注册成功", data={
                    'id': user.id,
                    'username': user.username,
                    'email': user.email,
                    'phone': user.phone,
                    'user_type': user.user_type,
                    'status': user.status,
                })
            except Exception as e:
                return api_response(ResponseCode.INTERNAL_SERVER_ERROR, f"注册失败：{str(e)}")
        return api_response(ResponseCode.BAD_REQUEST, f"请求数据无效{serializer.errors}")


class CreateUserView(APIView):
    """
    新增用户接口
    """

    permission_classes = [AllowAny]
    authentication_classes = [JWTAuthentication]

    @swagger_auto_schema(
        operation_description="创建一个新用户",
        request_body=UserCreateSerializer,
        responses={
            200: openapi.Response(
                description="用户创建成功",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'code': openapi.Schema(type=openapi.TYPE_INTEGER, description="响应状态码"),
                        'msg': openapi.Schema(type=openapi.TYPE_STRING, description="响应消息"),
                        'data': openapi.Schema(
                            type=openapi.TYPE_OBJECT,
                            properties={
                                'id': openapi.Schema(type=openapi.TYPE_STRING, description="用户 ID"),
                                'username': openapi.Schema(type=openapi.TYPE_STRING, description="用户名"),
                                'user_type': openapi.Schema(type=openapi.TYPE_INTEGER, description="用户类型"),
                                'status': openapi.Schema(type=openapi.TYPE_STRING,
                                                         description="用户是否激活（启用enable、禁用disabled）"),
                                'phone': openapi.Schema(type=openapi.TYPE_STRING, description="用户电话"),
                                'email': openapi.Schema(type=openapi.TYPE_STRING, description="用户邮箱")
                            }
                        )
                    }
                )
            ),
            400: openapi.Response(description="请求数据无效"),
            500: openapi.Response(description="服务器内部错误")
        },
        tags=["用户管理"]
    )
    def post(self, request, *args, **kwargs):
        serializer = UserCreateSerializer(data=request.data)
        if serializer.is_valid():
            try:
                user = serializer.save()
                return api_response(ResponseCode.SUCCESS, "用户创建成功", data={
                    'id': user.id,
                    'username': user.username,
                    'user_type': user.user_type,
                    'status': user.status,
                    'phone': user.phone,
                    'email': user.email,
                })
            except Exception as e:
                return api_response(ResponseCode.INTERNAL_SERVER_ERROR, f"创建用户失败：{str(e)}")
        return api_response(ResponseCode.BAD_REQUEST, f"请求数据无效{serializer.errors}")


class LoginUserView(APIView):
    """
    用户登录接口
    """

    permission_classes = [AllowAny]
    authentication_classes = []

    @swagger_auto_schema(
        operation_description="用户登录",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=['username', 'password'],
            properties={
                'username_or_email': openapi.Schema(type=openapi.TYPE_STRING, description="用户名或邮箱"),
                'password': openapi.Schema(type=openapi.TYPE_STRING, description="密码"),
            }
        ),
        responses={
            200: openapi.Response(
                description="登录成功",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'code': openapi.Schema(type=openapi.TYPE_INTEGER),
                        'msg': openapi.Schema(type=openapi.TYPE_STRING),
                        'data': openapi.Schema(
                            type=openapi.TYPE_OBJECT,
                            properties={
                                'id': openapi.Schema(type=openapi.TYPE_STRING),
                                'username': openapi.Schema(type=openapi.TYPE_STRING),
                                'user_type': openapi.Schema(type=openapi.TYPE_INTEGER),
                                'status': openapi.Schema(type=openapi.TYPE_STRING),
                                'phone': openapi.Schema(type=openapi.TYPE_STRING),
                                'email': openapi.Schema(type=openapi.TYPE_STRING),
                            }
                        )
                    }
                )
            ),
            400: openapi.Response(description="请求数据无效"),
            401: openapi.Response(description="账号或密码错误"),
            404: openapi.Response(description="用户不存在")
        },
        tags=["登录注册"]
    )
    def post(self, request, *args, **kwargs):
        username_or_email = request.data.get('username_or_email')
        password = request.data.get('password')
        if not username_or_email or not password:
            return api_response(ResponseCode.BAD_REQUEST, "账号和密码不能为空")
        user = None
        try:
            if '@' in username_or_email:
                pattern = r'^.+@.+\..+$'
                if re.match(pattern, username_or_email):
                    user = User.objects.get(email=username_or_email)
                else:
                    return api_response(ResponseCode.BAD_REQUEST, "邮箱格式不正确")
            else:
                user = User.objects.get(username=username_or_email)
        except ObjectDoesNotExist:
            return api_response(ResponseCode.NOT_FOUND, "用户不存在")
        if not user.check_password(password):
            return api_response(ResponseCode.UNAUTHORIZED, "密码错误")

        # 更新登录时间
        user.last_login = timezone.now()
        user.save()

        # 使用 rest_framework_simplejwt 生成 token
        refresh = RefreshToken.for_user(user)
        access_token = str(refresh.access_token)
        refresh_token = str(refresh)

        data = {
            'userInfo': {
                'id': user.id,
                'username': user.username,
                'user_type': user.user_type,
                'status': user.status,
                'phone': user.phone,
                'email': user.email,
            },
            'token': {
                'access_token': access_token,
                'refresh_token': refresh_token
            }
        }

        return api_response(ResponseCode.SUCCESS, "登录成功", data=data)


class LogoutView(APIView):
    """
    用户登出接口
    """

    permission_classes = [AllowAny]
    authentication_classes = [JWTAuthentication]

    @swagger_auto_schema(
        operation_description="用户登出接口",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=['refresh'],
            properties={
                'refresh': openapi.Schema(
                    type=openapi.TYPE_STRING,
                    description="refresh token"
                ),
            }
        ),
        responses={
            200: '登出成功！',
            400: '用户未登录或token无效！'
        },
        tags=["登录注册"]
    )
    def delete(self, request):
        try:
            # 获取用户的 Refresh Token
            refresh_token = request.data.get('refresh')
            if not refresh_token:
                return api_response(ResponseCode.BAD_REQUEST, "未传入token")

            # 验证 refresh token 并将其加入黑名单
            refresh = RefreshToken(refresh_token)
            refresh.blacklist()  # 将 token 加入黑名单
            return api_response(ResponseCode.SUCCESS, "登出成功！")
        except TokenError:
            return api_response(ResponseCode.BAD_REQUEST, "无效的token，登出失败！")


class ListUserView(APIView):
    """
    获取用户列表接口
    """

    permission_classes = [AllowAny]
    authentication_classes = [JWTAuthentication]

    @swagger_auto_schema(
        operation_description="获取用户列表",
        manual_parameters=[
            openapi.Parameter('status', openapi.IN_QUERY, description="用户状态（enable/disabled）", type=openapi.TYPE_STRING),
            openapi.Parameter('keywords', openapi.IN_QUERY, description="用户名", type=openapi.TYPE_STRING),
        ],
        responses={
            200: openapi.Response(
                description="获取成功",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'code': openapi.Schema(type=openapi.TYPE_INTEGER),
                        'msg': openapi.Schema(type=openapi.TYPE_STRING),
                        'data': openapi.Schema(
                            type=openapi.TYPE_ARRAY,
                            items=openapi.Schema(
                                type=openapi.TYPE_OBJECT,
                                properties={
                                    'id': openapi.Schema(type=openapi.TYPE_STRING),
                                    'username': openapi.Schema(type=openapi.TYPE_STRING),
                                    'user_type': openapi.Schema(type=openapi.TYPE_INTEGER),
                                    'status': openapi.Schema(type=openapi.TYPE_STRING),
                                    'phone': openapi.Schema(type=openapi.TYPE_STRING),
                                    'email': openapi.Schema(type=openapi.TYPE_STRING),
                                }
                            )
                        )
                    }
                )
            ),
            400: openapi.Response(description="无效的参数"),
        },
        tags=["用户管理"]
    )
    def get(self, request, *args, **kwargs):
        status_param = request.GET.get('status')
        keywords = request.GET.get('keywords')
        page = request.query_params.get("pageNo", 1)
        page_size = request.query_params.get("pageSize", 10)
        queryset = User.objects.all().order_by('-create_time')

        if status_param is not None:
            if status_param.lower() in ['enable', 'disabled']:
                return api_response(ResponseCode.BAD_REQUEST, "无效的 status 参数")
            queryset = queryset.filter(status=status_param.lower())

        if keywords:
            queryset = queryset.filter(
                Q(username__icontains=keywords) | Q(first_name__icontains=keywords) | Q(last_name__icontains=keywords)
            )

        paginator = CustomPageNumberPagination()
        # 设置分页参数
        paginator.page_size = int(page_size)  # 每页的条数
        paginator.page_query_param = 'pageNo'  # 页码的参数名
        paginator.page_size_query_param = 'page_size'  # 每页数据条数的参数名
        result_page = paginator.paginate_queryset(queryset, request)
        serializer = UserListSerializer(result_page, many=True)  # 序列化多个用户
        paginated_response = paginator.get_paginated_response(serializer.data)

        return api_response(ResponseCode.SUCCESS, "获取用户列表成功", paginated_response.data)


class UserPackageListView(APIView):
    """
    获取用户和套餐信息列表接口
    """

    permission_classes = [AllowAny]
    authentication_classes = [JWTAuthentication]

    @swagger_auto_schema(
        operation_description="获取用户和套餐信息列表",
        manual_parameters=[
            openapi.Parameter('package_status', openapi.IN_QUERY,
                              description="用户套餐状态（活跃active、已过期expired、已禁用disabled）",
                              type=openapi.TYPE_STRING),
            openapi.Parameter('duration', openapi.IN_QUERY, description="会员类型（月度monthly、季度quarter、年度yearly）",
                              type=openapi.TYPE_STRING),
            openapi.Parameter('keywords', openapi.IN_QUERY, description="用户名或邮箱", type=openapi.TYPE_STRING),
        ],
        responses={
            200: openapi.Response(
                description="获取成功",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'code': openapi.Schema(type=openapi.TYPE_INTEGER),
                        'msg': openapi.Schema(type=openapi.TYPE_STRING),
                        'data': openapi.Schema(
                            type=openapi.TYPE_ARRAY,
                            items=openapi.Schema(
                                type=openapi.TYPE_OBJECT,
                                properties={
                                    'username': openapi.Schema(type=openapi.TYPE_STRING, description="用户名"),
                                    'email': openapi.Schema(type=openapi.TYPE_STRING, description="邮箱"),
                                    'dynamic_status': openapi.Schema(type=openapi.TYPE_STRING,
                                                                     description="用户或套餐状态"),
                                    'package_name': openapi.Schema(type=openapi.TYPE_STRING, description="套餐名称"),
                                    'expiration_time': openapi.Schema(type=openapi.TYPE_STRING, description="到期时间"),
                                }
                            )
                        )
                    }
                )
            ),
            400: openapi.Response(description="无效的参数"),
        },
        tags=["用户管理"]
    )
    def get(self, request, *args, **kwargs):
        package_status = request.query_params.get('package_status')
        duration = request.query_params.get('duration')
        keywords = request.query_params.get('keywords')
        page = request.query_params.get("pageNo", 1)
        page_size = request.query_params.get("pageSize", 10)
        queryset = User.objects.all().order_by('-create_time')

        if package_status is not None:
            if package_status.lower() in ['active', 'expired', 'disabled']:
                queryset = queryset.filter(packages__status=package_status.lower())
            else:
                return api_response(ResponseCode.BAD_REQUEST, "无效的 status 参数")

        if duration:
            queryset = queryset.filter(packages__package__duration=duration)

        if keywords:
            pattern = r'^.+@.+\..+$'
            if re.match(pattern, keywords):
                queryset = queryset.filter(email=keywords)
            else:
                queryset = queryset.filter(
                    Q(username__icontains=keywords) | Q(first_name__icontains=keywords) | Q(
                        last_name__icontains=keywords)
                )

        paginator = CustomPageNumberPagination()
        # 设置分页参数
        paginator.page_size = int(page_size)  # 每页的条数
        paginator.page_query_param = 'pageNo'  # 页码的参数名
        paginator.page_size_query_param = 'page_size'  # 每页数据条数的参数名
        result_page = paginator.paginate_queryset(queryset, request)
        serializer = UserSerializer(result_page, many=True)  # 序列化多个用户
        paginated_response = paginator.get_paginated_response(serializer.data)

        return api_response(ResponseCode.SUCCESS, "获取用户列表成功", paginated_response.data)


class UserInfoView(APIView):
    """
    获取用户详情接口
    """

    permission_classes = [AllowAny]
    authentication_classes = [JWTAuthentication]

    @swagger_auto_schema(
        operation_description="获取用户详情",
        responses={
            200: openapi.Response(
                description="获取成功",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'code': openapi.Schema(type=openapi.TYPE_INTEGER),
                        'msg': openapi.Schema(type=openapi.TYPE_STRING),
                        'data': openapi.Schema(
                            type=openapi.TYPE_OBJECT,
                            properties={
                                'id': openapi.Schema(type=openapi.TYPE_STRING),
                                'username': openapi.Schema(type=openapi.TYPE_STRING),
                                'user_type': openapi.Schema(type=openapi.TYPE_INTEGER),
                                'status': openapi.Schema(type=openapi.TYPE_STRING),
                                'phone': openapi.Schema(type=openapi.TYPE_STRING),
                                'email': openapi.Schema(type=openapi.TYPE_STRING),
                            }
                        )
                    }
                )
            ),
            404: openapi.Response(description="用户不存在")
        },
        tags=["用户管理"]
    )
    def get(self, request, user_id, *args, **kwargs):
        try:
            user = User.objects.get(pk=user_id)
        except ObjectDoesNotExist:
            return api_response(ResponseCode.NOT_FOUND, "用户不存在")
        try:
            serializer = UserInfoSerializer(user)
            return api_response(ResponseCode.SUCCESS, "获取用户详情成功", serializer.data)
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, f"获取用户详情失败：{str(e)}")


class UpdateUserView(APIView):
    """
    更新用户接口
    """

    permission_classes = [AllowAny]
    authentication_classes = [JWTAuthentication]

    @swagger_auto_schema(
        operation_description="更新用户信息",
        request_body=UserUpdateSerializer,
        responses={
            200: openapi.Response(
                description="更新成功",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'code': openapi.Schema(type=openapi.TYPE_INTEGER),
                        'msg': openapi.Schema(type=openapi.TYPE_STRING),
                        'data': openapi.Schema(
                            type=openapi.TYPE_OBJECT,
                            properties={
                                'id': openapi.Schema(type=openapi.TYPE_STRING),
                                'username': openapi.Schema(type=openapi.TYPE_STRING),
                                'user_type': openapi.Schema(type=openapi.TYPE_INTEGER),
                                'status': openapi.Schema(type=openapi.TYPE_STRING),
                                'phone': openapi.Schema(type=openapi.TYPE_STRING),
                                'email': openapi.Schema(type=openapi.TYPE_STRING),
                            }
                        )
                    }
                )
            ),
            400: openapi.Response(description="请求数据无效"),
            404: openapi.Response(description="用户不存在")
        },
        tags=["用户管理"]
    )
    def put(self, request, user_id, *args, **kwargs):
        try:
            user = User.objects.get(pk=user_id)
        except ObjectDoesNotExist:
            return api_response(ResponseCode.NOT_FOUND, "用户不存在")
        serializer = UserUpdateSerializer(user, data=request.data, partial=True)
        if serializer.is_valid():
            user = serializer.save()
            data = {
                'id': user.id,
                'username': user.username,
                'user_type': user.user_type,
                'status': user.status,
                'phone': user.phone,
                'email': user.email,
            }
            return api_response(ResponseCode.SUCCESS, "用户更新成功", data=data)
        return api_response(ResponseCode.BAD_REQUEST, f"请求数据无效{serializer.errors}")


class ChangeUserStatusView(APIView):
    """
    修改用户状态接口
    """

    permission_classes = [AllowAny]
    authentication_classes = [JWTAuthentication]

    @swagger_auto_schema(
        operation_description="修改用户状态接口",
        responses={
            200: openapi.Response(
                description="更新成功",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'code': openapi.Schema(type=openapi.TYPE_INTEGER),
                        'msg': openapi.Schema(type=openapi.TYPE_STRING),
                        'data': openapi.Schema(
                            type=openapi.TYPE_OBJECT,
                            properties={
                                'id': openapi.Schema(type=openapi.TYPE_STRING),
                                'username': openapi.Schema(type=openapi.TYPE_STRING),
                                'user_type': openapi.Schema(type=openapi.TYPE_INTEGER),
                                'status': openapi.Schema(type=openapi.TYPE_STRING),
                                'phone': openapi.Schema(type=openapi.TYPE_STRING),
                                'email': openapi.Schema(type=openapi.TYPE_STRING),
                            }
                        )
                    }
                )
            ),
            400: openapi.Response(description="请求数据无效"),
            404: openapi.Response(description="用户不存在")
        },
        tags=["用户管理"]
    )
    def put(self, request, user_id, *args, **kwargs):
        try:
            try:
                user = User.objects.get(pk=user_id)
            except ObjectDoesNotExist:
                return api_response(ResponseCode.NOT_FOUND, "用户不存在")

            if user.status == 'enable':
                user.status = 'disabled'
            else:
                user.status = 'enable'
            user.save()

            serializer = UserInfoSerializer(user)

            return api_response(ResponseCode.SUCCESS, "用户状态更新成功", data=serializer.data)
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, f"更新用户状态失败：{str(e)}")


class DeleteUserView(APIView):
    """
    删除用户接口
    """

    permission_classes = [AllowAny]
    authentication_classes = [JWTAuthentication]

    @swagger_auto_schema(
        operation_description="删除用户",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=['user_ids'],
            properties={
                'user_ids': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Schema(type=openapi.TYPE_STRING),
                                           description="用户ID列表"),
            }
        ),
        responses={
            200: openapi.Response(description="删除成功"),
            400: openapi.Response(description="请求数据无效"),
            404: openapi.Response(description="用户不存在")
        },
        tags=["用户管理"]
    )
    def delete(self, request, *args, **kwargs):
        user_ids = request.data.get('user_ids')

        if not user_ids or not isinstance(user_ids, list):
            return api_response(ResponseCode.BAD_REQUEST, "无效的请求数据，必须提供用户ID列表")

        not_found_users = []
        for user_id in user_ids:
            try:
                user = User.objects.get(id=user_id)
                user.delete()
            except ObjectDoesNotExist:
                not_found_users.append(user_id)
        if not_found_users:
            return api_response(ResponseCode.NOT_FOUND,
                                f"成功删除用户 {len(user_ids) - len(not_found_users)} 个，未删除用户 {len(not_found_users)} 个")
        return api_response(ResponseCode.NO_CONTENT, "用户删除成功")
